package com.tuantuan.dao;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
import org.springframework.orm.ibatis.SqlMapClientCallback;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapExecutor;
import com.ibatis.sqlmap.client.event.RowHandler;
import com.ibatis.sqlmap.engine.execution.BatchException;
import com.ibatis.sqlmap.engine.execution.BatchResult;
import com.tuantuan.model.DatagridPageDTO;
import com.tuantuan.utils.LogUtils;
public class BaseDao extends SqlMapClientDaoSupport{

	  @Resource(name="sqlMapClient")  //通过bean名称注入   
	   private SqlMapClient sqlMapClient;  
	      
	    @PostConstruct  //完成sqlMapClient初始化工作   
	    public void initSqlMapClient(){  
	        super.setSqlMapClient(sqlMapClient);  
	    }
	  
	    /*
	     * 回调接口，用于与iBATIS的SqlMapExecutor接口工作数据访问代码
	     */
	    @SuppressWarnings("unchecked")  
	    public <T> T execute(SqlMapClientCallback action) throws DataAccessException {  
	        return (T) getSqlMapClientTemplate().execute(action);  
	    }  
	    /*
	     * 查询单个对象或者其他
	     * 返回的参数是对象也可以是基本数据类型(Integer)
	     * int java.lang.String
	     */
	    @SuppressWarnings("unchecked")  
	    public <T> T  queryForObject(String sqlId) throws DataAccessException {  
	        return (T) getSqlMapClientTemplate().queryForObject(sqlId);  
	    }  
	  /*
	   * 匿名参数查询
	   */
	    @SuppressWarnings("unchecked")  
	    public <T> T  queryForObject(final String sqlId, final Object parameterObject) throws DataAccessException {  
	        return (T) getSqlMapClientTemplate().queryForObject(sqlId, parameterObject);  
	    }  
	  
	    @SuppressWarnings("unchecked")  
	    public <T> T  queryForObject(final String sqlId, final Object parameterObject, final Object resultObject) throws DataAccessException {  
	        return (T) getSqlMapClientTemplate().queryForObject(sqlId, parameterObject, resultObject);  
	    }  
	    /*
	     * 查询集合
	     * 返回的参数 java.util.hashMap
	     */
	    public List<?> queryForList(String sqlId) throws DataAccessException {  
	        return queryForList(sqlId, null);  
	    }  
	  
	    public List<?> queryForList(final String sqlId, final Object parameterObject) throws DataAccessException {  
	        return getSqlMapClientTemplate().queryForList(sqlId, parameterObject);  
	    }  
	    
	    /**
	     * 
	     * 插件分页查询
	     * 方法名：queryForDatagridPage<BR>
	     * 创建人：许耀东 <BR>
	     * 时间：2015年11月10日-下午10:54:14 <BR>
	     * @param sqlId
	     * @param datagridPageDTO
	     * @return T<BR>
	     */
		public <T extends DatagridPageDTO> T queryForDatagridPage(String sqlId, T datagridPageDTO) {
			Map<String, Object> countMap = (Map<String, Object>) this.queryForObject(sqlId, datagridPageDTO); // 查询全部数据数量

			// 设置总条数
			datagridPageDTO.setTotal(this.getCount(countMap.get("counts")));

			datagridPageDTO.setDoAount(false);
			// datagridPageDTO.countEndAndIndex();
			// 设置实际数据内容
			datagridPageDTO.setRows(this.queryForList(sqlId, datagridPageDTO));
			return datagridPageDTO;
		}

		private int getCount(Object countsObj) {
			int count = 0;
			if (countsObj instanceof BigDecimal) {
				count = ((BigDecimal) countsObj).intValue();
			} else if (countsObj instanceof Long) {
				count = ((Long) countsObj).intValue();
			} else if (countsObj instanceof Integer) {
				count = ((Integer) countsObj).intValue();
			} else {
				LogUtils.error("obj is error , the obj is :" + countsObj);
			}
			return count;
		}
	    
	    
	    
	  /**
	   * 
	   * 不带参数分页查询<BR>
	   * 方法名：queryForList<BR>
	   * 创建人：许耀东 <BR>
	   * 时间：2015年7月26日-下午3:31:03 <BR>
	   * @param sqlId
	   * @param skipResults，开始页数
	   * @param maxResults，查询的数目
	   * @return
	   * @throws DataAccessException List<?><BR>
	   */
	    public List<?> queryForList(String sqlId, int skipResults, int maxResults)throws DataAccessException {  
	        return queryForList(sqlId, null, skipResults, maxResults);  
	    }  
	    /**
	     * 带参数分页查询
	     * 方法名：queryForList<BR>
	     * 创建人：许耀东 <BR>
	     * 时间：2015年7月26日-下午3:32:07 <BR>
	     * @param sqlId
	     * @param parameterObject
	     * @param skipResults，开始页数
	     * @param maxResults，查询的数目
	     * @return
	     * @throws DataAccessException List<?><BR>
	     */
	    public List<?> queryForList(final String sqlId, final Object parameterObject, final int skipResults, final int maxResults) throws DataAccessException {  
	        return getSqlMapClientTemplate().queryForList(sqlId, parameterObject, skipResults, maxResults);  
	    }  
	  /*
	   * 读取所有行
	   */
	    public void queryWithRowHandler(String sqlId, RowHandler rowHandler)throws DataAccessException {  
	        queryWithRowHandler(sqlId, null, rowHandler);  
	    }  
	  
	    public void queryWithRowHandler( final String sqlId, final Object parameterObject, final RowHandler rowHandler) throws DataAccessException {  
	        getSqlMapClientTemplate().queryWithRowHandler(sqlId, parameterObject, rowHandler);  
	    }  
	  
	    public Map<?,?> queryForMap( final String sqlId, final Object parameterObject, final String keyProperty) throws DataAccessException {  
	        return getSqlMapClientTemplate().queryForMap(sqlId, parameterObject, keyProperty);  
	    }  
	  
	    public Map<?,?> queryForMap( final String sqlId, final Object parameterObject, final String keyProperty, final String valueProperty) throws DataAccessException {  
	        return getSqlMapClientTemplate().queryForMap(sqlId, parameterObject, keyProperty, valueProperty);  
	    }  
	  
	    public <T> T insert(String sqlId) throws DataAccessException {  
	        return (T) getSqlMapClientTemplate().insert(sqlId, null);  
	    } 
	    
	    @SuppressWarnings("unchecked")  
	    public <T> T insert(final String sqlId, final Object parameterObject) throws DataAccessException {  
	        return (T) getSqlMapClientTemplate().insert(sqlId, parameterObject);  
	    }  
	    /**
	     * 
	     * 批量添加数据<BR>
	     * 方法名：insertBatch<BR>
	     * 创建人：许耀东 <BR>
	     * 时间：2015年7月26日-上午11:06:51 <BR>
	     * @param sqlId
	     * @param list void<BR>
	     */
	    public <T> void insertBatch(final String sqlId, final List<T> list) {   
	        getSqlMapClientTemplate().execute(  
	                new SqlMapClientCallback() {   
	                    public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {   
	                        executor.startBatch();   
	                        for (int i = 0; i < list.size(); i++) {   
	                            T t =  (T)list.get(i);   
	                            executor.insert(sqlId, t);   
	                            if (i%500 == 0) {  
	                            	//每1000条数据就向数据库提交要运行的一批命令。
	                            	//如果所有命令都成功运行，则返回一个更新计数数组。
	                                executor.executeBatch(); 
	                               
	                             }     
	                        }   
	                        executor.executeBatch();   
	                        return null;   
	                    }   
	                });   
	        }  
	    
	  
	  
	      
	    public int update(String sqlId) throws DataAccessException {  
	        return update(sqlId, null);  
	    }  
	  
	    public int update(final String sqlId, final Object parameterObject) throws DataAccessException {  
	        Integer result = (Integer) execute(new SqlMapClientCallback() {  
	            public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {  
	                return new Integer(executor.update(sqlId, parameterObject));  
	            }  
	        });  
	        return result.intValue();  
	    }  
	   /**
	    * 
	    * <BR>
	    * 方法名：update<BR>
	    * 创建人：许耀东 <BR>
	    * 时间：2015年7月26日-上午11:06:00 <BR>
	    * @param sqlId
	    * @param parameterObject
	    * @param requiredRowsAffected 影响的行数
	    * @throws DataAccessException void<BR>
	    */
	    public void update(String sqlId, Object parameterObject, int requiredRowsAffected)  
	            throws DataAccessException {  
	  
	        int actualRowsAffected = update(sqlId, parameterObject);  
	        if (actualRowsAffected != requiredRowsAffected) {  
	            throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(  
	                    sqlId, requiredRowsAffected, actualRowsAffected);  
	        }  
	    }  
	  
	    /**
	     * 
	     * 批量更新数据<BR>
	     * 方法名：updateBatch<BR>
	     * 创建人：许耀东 <BR>
	     * 时间：2015年7月26日-上午11:05:04 <BR>
	     * @param sqlId
	     * @param list
	     * @return int 影响的行数，也就是成功的行数<BR>
	     */
	    public <T> int updateBatch(final String sqlId, final List<T> list) {   
	        if(list == null || list.isEmpty()){  
	            return 0;  
	        }  
	          
	        SqlMapClientCallback callback = new SqlMapClientCallback() {  
	            public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {  
	                executor.startBatch();  
	                for (Object obj : list) {  
	                    executor.update(sqlId, obj);  
	                }  
	                try {  
	                    return executor.executeBatchDetailed();  
	                } catch (BatchException e) {  
	                    LogUtils.error(e.getMessage(), e);
	                    throw new SQLException("Batch update failed!");  
	                }  
	            }  
	        };  
	        List<BatchResult> retList = (List<BatchResult>) getSqlMapClientTemplate().execute(callback);  
	        return batchResult(retList);  
	    }  
	    
	    public int delete(String sqlId) throws DataAccessException {  
	        return delete(sqlId, null);  
	    }  
	  
	    public int delete(final String sqlId, final Object parameterObject)  
	            throws DataAccessException {  
	  
	        Integer result = (Integer) execute(new SqlMapClientCallback() {  
	            public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {  
	                return new Integer(executor.delete(sqlId, parameterObject));  
	            }  
	        });  
	        return result.intValue();  
	    }  
	    /**
	     * 
	     * 方法名：delete<BR>
	     * 创建人：许耀东 <BR>
	     * 时间：2015年7月26日-上午11:04:10 <BR>
	     * @param sqlId
	     * @param parameterObject
	     * @param requiredRowsAffected 影响的行数
	     * @throws DataAccessException void<BR>
	     */
	    public void delete(String sqlId, Object parameterObject, int requiredRowsAffected) throws DataAccessException {  
	  
	        int actualRowsAffected = delete(sqlId, parameterObject);  
	        if (actualRowsAffected != requiredRowsAffected) {  
	            throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(  
	                    sqlId, requiredRowsAffected, actualRowsAffected);  
	        }  
	    }  
	  
	   
	      
	    /** 
	     * 从批处理结果返回处理成功的记录数 
	     * @param batchResultList 
	     * @return count 
	     */  
	    private int batchResult(List<BatchResult> batchResultList) {  
	        int count = 0;  
	        if (batchResultList != null && !batchResultList.isEmpty()) {  
	            BatchResult result = batchResultList.get(0);  
	            if (result != null) {  
	                for (int i : result.getUpdateCounts()) {  
	                    if (i == java.sql.Statement.SUCCESS_NO_INFO) {  
	                        count++;  
	                    } else {  
	                        count += i;  
	                    }  
	                }  
	            }  
	        }  
	        return count;  
	    }  
	  
	  
	  
	  
}
